0010 - Feature Flag와 AB Test

Feature Flag로 배포와 출시를 분리하고, A/B Test의 그룹 배정·노출 로깅·지표 분석으로 기능의 효과를 검증하는 방법

TIL

개발이 끝나면 바로 출시해야 할까

클라이언트 개발은 끝났는데 백엔드 API는 아직 준비되지 않았다고 해보자.
개발이 모두 끝나더라도 마케팅이나 이벤트 일정 때문에 공개를 기다려야 할 수 있다.
그때마다 작업 브랜치를 오래 유지하면 다른 작업과 충돌할 가능성이 커진다.

모바일 앱에는 스토어 심사에 걸리는 시간도 있다.
Android와 iPhone 앱을 동시에 제출해도 같은 날 심사가 끝난다는 보장은 없다.

스토어공식 안내 기준 심사·처리 시간
Google Play몇 시간에서 최대 7일, 예외적으로 그 이상. 제출부터 게시까지 최소 1주일의 여유를 권장
App Store평균적으로 제출 건의 90%를 24시간 이내에 심사. 반려나 추가 확인으로 지연될 수 있음

2026년 9월 확인한 공식 안내이며, 사용자의 설치 완료까지 걸리는 시간은 아니다. Google Play — 검토 및 게시 시점 관리, Apple — App Review

그래서 코드를 전달하는 시점과 사용자가 기능을 쓰기 시작하는 시점을 나눈다.

구분의미
배포(Deployment)새 기능이 포함된 앱 버전을 전달하는 것
출시(Release)사용자가 해당 기능을 이용할 수 있게 공개하는 것

새 기능을 OFF 상태로 미리 배포하고, 양쪽 앱과 백엔드가 준비되면 활성화할 수 있다.
다만 사용자가 앱을 업데이트해야 새 코드가 기기에 도달하므로, 구버전 앱에 없는 기능까지 켤 수는 없다.


Feature Flag란 무엇인가

Feature Flag는 코드를 다시 배포하지 않고 설정에 따라 기능의 동작을 선택할 수 있게 하는 장치다.

홈에 새로운 추천 영역을 추가했다면, Flag가 ON일 때는 새 영역을 보여주고 OFF일 때는 기존 홈을 보여준다.
여기서는 ON/OFF로 설명하지만, 설정값이 Boolean으로만 제한되는 것은 아니다.

배포와 출시를 분리하는 가치

  • 개발 일정 분리: 클라이언트가 먼저 끝나면 비활성 상태로 배포하고 다음 작업을 진행할 수 있다.
  • 비즈니스 일정 분리: 마케팅이나 이벤트 시작일에 맞춰 기능을 공개할 수 있다.
  • 점진적 공개: 내부 사용자부터 일부 사용자, 전체 사용자로 대상을 넓힐 수 있다.
  • 장애 대응: 문제가 생기면 새 기능을 끄고 기존 기능으로 전환할 수 있다.

외부 일정 때문에 완료된 코드를 오래 보관할 필요가 줄어든다.
다만 코드 배포를 기다리게 하던 의존성을 기능 활성화 조건으로 옮기는 것이므로, 공개 전에는 백엔드와 관련 작업이 준비되어야 한다.

OFF 상태로 배포하기 전에 확인할 것

버튼만 숨겨도 백그라운드 작업이나 딥링크를 통해 새 로직이 실행될 수 있다.
실제 Flag 분기와 최종 API를 함께 검증해야 한다.

상태확인할 내용
OFF기존 기능이 유지되고 준비되지 않은 API를 호출하지 않는가
ONMock이 아닌 최종 API와 정상 동작하는가
설정 조회 실패정해둔 fallback으로 동작하는가
실행 중 설정 변경진행 중인 화면과 작업이 어긋나지 않는가

클라이언트가 새 백엔드 기능에 의존한다면 서버를 먼저 준비하고 검증한 뒤 클라이언트 노출을 연다.
Flag를 끄더라도 이미 실행된 작업이나 저장된 데이터까지 되돌아가지는 않는다.


Feature Flag 기능 요구사항

누구에게 제공하고, 언제 적용하며, 실패하면 어떻게 동작할지를 정해야 한다.

요구사항정해야 할 내용
환경 분리QA와 프로덕션의 설정 구분
대상 지정사용자 ID, 앱 버전, 내부 사용자 여부 등의 조건
fallback설정이 없거나 조회에 실패했을 때의 기본 동작
캐시와 적용 시점설정을 언제 갱신하고 화면에 반영할지
공통 사용Presentation과 Domain에서 같은 기준으로 조회

fallback

fallback은 설정을 정상적으로 얻지 못했을 때 사용자에게 제공할 동작이다.
새 추천 영역에 문제가 생겼다면 기존 추천을 보여주거나 해당 영역을 숨길 수 있다.
기능별로 기본 동작을 정하고, 정상적인 OFF와 조회 실패를 구분해 기록한다.

설정 적용 시점

사용자가 입력 중일 때 설정이 바뀌어 화면이 교체되면 흐름이 끊길 수 있다.
새 설정은 다음 화면 진입처럼 안전한 시점에 적용하도록 정한다. Firebase — 설정 로딩 전략

캐시나 오프라인 상태 때문에 긴급 OFF가 모든 기기에 즉시 반영되지는 않을 수 있다.


A/B Test는 무엇을 검증하는가

새 추천 화면을 출시한 뒤 클릭이 늘었다고 해보자.
새 화면의 효과일 수도 있지만, 같은 기간에 진행한 이벤트 때문일 수도 있다.

A/B Test는 사용자를 무작위로 나누어 서로 다른 시안을 같은 기간에 제공하고, 사전에 정한 지표를 비교하는 실험이다.
보통 A는 기존 동작인 대조군, B는 새 동작인 실험군이며 A/B/C처럼 여러 시안을 비교할 수도 있다.

구분Feature FlagA/B Test
핵심 질문누구에게 어떤 기능을 열 것인가어떤 시안이 목표 지표를 개선하는가
필요한 것조건 평가와 기본 동작그룹 배정, 노출·행동 기록, 결과 분석

Feature Flag로 실험 시안을 제공할 수 있지만, 화면을 나누어 보여주는 것만으로는 부족하다.
배정과 측정, 분석이 연결되어야 한다.


먼저 가설과 지표를 정한다

추천 화면을 바꾼다면 다음처럼 가설을 세울 수 있다.

추천 코스의 정보를 자세히 보여주면, 사용자가 자신에게 맞는 코스를 찾아 저장할 확률이 높아질 것이다.

개선하려는 지표와 악화되어서는 안 되는 지표를 함께 정한다.

구분
주 지표정해진 기간 안에 코스를 저장한 사용자 비율
보조 지표추천 영역 클릭률, 상세 페이지 진입률
보호 지표(Guardrail)크래시율, 홈 로딩 시간, 이탈률

비율을 계산할 대상도 미리 정해야 한다.
클릭한 사용자만 골라 비교하면 시안에 따라 분석 대상이 달라져 결과가 왜곡될 수 있다.

토스의 푸시 실험도 CTR과 함께 활성 사용자·매출을 보호 지표로 관찰했다. 토스 — A/B Test 사례


A/B Test 기능 요구사항

요구사항정해야 할 내용
실험 대상어떤 사용자에게 실험을 진행할지
시안과 배정 비율A/B/C 중 무엇을 어떤 비율로 제공할지
배정 유지같은 사용자가 같은 시안을 경험하도록 할 기준
fallback평가 실패 시 제공할 기본 시안과 실패 기록
공통 사용Presentation과 Domain에서 같은 배정 결과 사용
측정실제 노출과 목표 행동을 연결하는 로그

실험 대상과 배정 비율

먼저 실험 대상을 정하고, 그 안에서 그룹을 나눈다.
사용자의 20%를 실험 대상으로 삼고 A와 B에 절반씩 배정하면, 전체의 약 10%씩 각 시안을 보게 된다.
반드시 50:50이어야 하는 것은 아니며, 실험 목적에 맞춰 비율을 정할 수 있다.

같은 사용자에게 같은 시안 제공하기

화면을 열 때마다 새로 배정하면 한 사용자가 A와 B를 번갈아 보게 된다.
이를 막기 위해 실험 ID와 사용자 식별자를 해시해 일관된 그룹에 배정할 수 있다. 결정적 버킷 배정 방식

일반적인 사용자 단위 실험에서는 실험 기간 동안 배정을 유지하는 것을 기본으로 한다.
홈에서 A를 보고 상세 화면에서 B로 바뀌면, 저장 행동이 어느 시안의 영향을 받았는지 판단하기 어려워진다.


배정, 노출, 전환을 구분한다

[0009 - 로깅](/blog/0009 - 로깅/)에서 정리한 비즈니스 메트릭 로깅이 여기서 필요하다.

단계의미
배정어떤 시안을 제공할지 결정추천 화면 B에 배정
노출시안이 실제 사용자 경험에 적용B 추천 영역이 표시됨
전환목표 행동이 발생추천 코스를 저장

설정값을 읽었다고 사용자가 기능을 봤다고 판단해서는 안 된다.
홈 아래쪽의 추천 영역까지 스크롤하지 않았다면 실제 UI 노출은 없을 수 있다.

로그에는 실험 ID, 적용한 시안, 분석용 사용자 식별자, 이벤트와 시각을 남겨 노출과 전환을 연결한다.
Compose 재구성 등으로 같은 노출을 중복 기록하지 않도록 주의한다.


결과는 어떻게 판단할까

전환율이 A는 10%, B는 11%라면 B가 1%p 높고, 상대적으로 10% 개선된 것이다.
하지만 표본이 적다면 우연한 차이일 수 있다.

  • 시작 전에 필요한 표본 수, 실험 기간, 중단 기준을 정한다.
  • 진행 중에는 로그 누락과 크래시·성능 같은 보호 지표를 확인한다.
  • 종료 후에는 차이가 우연인지, 실제 개선 폭이 의미 있는지, 보호 지표가 악화되지 않았는지 함께 판단한다.

수치가 잠깐 좋아졌다는 이유만으로 실험을 끝내거나 전체 출시를 결정하지 않는다. Microsoft — 실험 운영 가이드


Presentation과 Domain에서 함께 사용하기

홈 추천 기능을 기준으로 책임을 나누면 다음과 같다.
아래는 특정 SDK에 종속되지 않는 설계 예시다.

구성 요소맡는 책임
FeatureFlagReader기능 활성화 여부 제공
ExperimentReader실험 참여 여부와 시안 제공
Data 계층원격 설정 조회, 캐시와 fallback 처리
UseCase / ViewModel결정값을 데이터 조회와 화면 상태에 전달
Presentation결정에 맞는 UI 표시와 실제 노출 기록

Domain에는 SDK 타입 대신 앱에서 사용하는 인터페이스와 모델을 두고, Data 계층에서 구현한다.
Feature Flag의 노출 여부는 Boolean으로 표현할 수 있지만, A/B Test는 여러 시안과 미참여·평가 실패 상태를 구분해야 한다.
평가 실패로 기존 화면을 보여줬다고 정상 대조군으로 기록해서는 안 된다.

한 흐름에서 확보한 결정값을 데이터 조회, 화면 표시, 전환 로그에 함께 사용한다.
Domain과 Presentation이 각각 다시 조회해 다른 시안을 적용하는 일을 막기 위해서다.

두 기능을 함께 쓴다면 Flag가 OFF일 때는 기존 기능을 제공하고, ON일 때 실험 시안을 판단하는 식으로 우선순위를 정한다.


출시 후에는 분기를 정리한다

실험을 끝내고 전체 공개했다면 불필요한 Flag와 이전 시안의 코드를 제거한다.
분기가 쌓일수록 검증해야 할 조합과 유지보수 비용도 늘어난다.

다만 구버전 앱이 사용하는 원격 설정과 API는 호환성을 확인한 뒤 정리해야 한다.